import math
import random

# import numpy as np
# import matplotlib.pyplot as plt


class Submarine:
    # LEG_COUNT = 0
    NAME_EXTENSION = list(range(1, 10))[::-1]

    # _OFFSPRINGS = []

    # def __new__(cls, *args, **kwargs):
    #     instance = super(Submarine, cls).__new__(cls)
    #     cls._OFFSPRINGS.append(instance)
    #     return instance

    def __init__(self,
                 x: int,
                 y: int,
                 heading: int,
                 speed: int,
                 name: str = ""):
        if name:
            self.name = name
        elif self.NAME_EXTENSION:
            self.name = f"sub_{str(self.NAME_EXTENSION.pop())}"
        else:
            self.name = f"sub_{str(random.randint(10, 9999))}"
        self.x = x
        self.y = y
        self.heading = heading
        self.speed = speed
        self.leg_num = 0
        self.tracks = {self.leg_num: (self.x, self.y)}
        self.targets = {}
        self.interval = 3

    def add_target(self, target):
        self.targets.setdefault(target, {})

    @property
    def OFFSPRINGS(self):
        return self.__class__._OFFSPRINGS

    @property
    def siblings(self):
        return set(self._OFFSPRINGS) - {self}

    def __sub__(self, other):
        x_diff = self.x - other.x
        y_diff = self.y - other.y
        return math.sqrt(x_diff**2 + y_diff**2)

    def get_target_range(self, target):
        return self - target

    def get_target_bearing(self, target):
        x_diff = target.x - self.x
        y_diff = target.y - self.y
        if x_diff > 0 and y_diff == 0:
            return 90
        elif x_diff < 0 and y_diff == 0:
            return 270
        elif x_diff == 0 and y_diff > 0:
            return 0
        elif x_diff == 0 and y_diff < 0:
            return 180
        elif x_diff == 0 and y_diff == 0:
            return 0

        if x_diff > 0 and y_diff > 0:
            return math.degrees(math.atan(x_diff / y_diff))
        elif x_diff < 0 and y_diff < 0 or x_diff > 0 and y_diff < 0:
            return math.degrees(math.atan(x_diff / y_diff)) + 180
        elif x_diff < 0 and y_diff > 0:
            return math.degrees(math.atan(x_diff / y_diff)) + 360

    def get_los_cross_speed(self, target):
        raw_diff = abs(self.get_target_bearing(target) - self.heading)
        if 0 <= raw_diff <= 90:
            angle = raw_diff
        elif 90 < raw_diff <= 180:
            angle = 180 - raw_diff
        elif 180 < raw_diff <= 270:
            angle = raw_diff - 180
        else:
            angle = 360 - raw_diff
        return self.speed * math.sin(math.radians(angle))

    def get_relative_movement_type(self, target):
        """
        相对于los的三种运动状态：
            0.	lag
            1.	lead
            2.	overlead
        """
        target_bearing, self_bearing = self.get_target_bearing(
            target), target.get_target_bearing(self)
        little_bearing, great_bearing = min(target_bearing, self_bearing), max(
            self_bearing, target_bearing)
        if (little_bearing < self.heading < great_bearing and
            (target.heading > great_bearing or target.heading < little_bearing)
            ) or (little_bearing < target.heading < great_bearing and
                  (self.heading > great_bearing
                   or self.heading < little_bearing)):
            return 0
        else:
            return 2

    def get_total_los_cross_speed(self, target):
        if self.get_relative_movement_type(target):
            return abs(
                self.get_los_cross_speed(target) -
                target.get_los_cross_speed(self))
        else:
            return self.get_los_cross_speed(
                target) + target.get_los_cross_speed(self)

    def _advance_one_leg(self):
        advance = self.speed * self.interval / 60
        advance_x = advance * math.sin(math.radians(self.heading))
        advance_y = advance * math.cos(math.radians(self.heading))
        self.x = self.x + advance_x
        self.y = self.y + advance_y
        self.leg_num += 1
        self.tracks[self.leg_num] = (self.x, self.y)

    def _observe_target(self):
        if self.targets:
            for target in self.targets:
                assert target.leg_num == self.leg_num
                self.targets[target][self.leg_num] = (
                    self.get_target_bearing(target),
                    self.get_target_range(target))

    # @classmethod
    # def sail(cls, duration: int = 40, interval: int = 3) -> None:
    #     cls.INTERVAL = interval
    #     index = 1
    #     while interval * index <= duration:
    #         cls.LEG_COUNT += 1
    #         for submarine in cls._OFFSPRINGS:
    #             assert submarine.leg_num + 1 == cls.LEG_COUNT
    #             submarine._advance_one_leg()

    #         for submarine in cls._OFFSPRINGS:
    #             submarine._observe_target()
    #         index += 1

    def __repr__(self):
        return f"<{self.name}, position ({self.x} {self.y}), heading: {self.heading}, speed: {self.speed}>"

    def calculate_ekelund_range(self, sub_target):
        assert self.leg_num == sub_target.leg_num > 0
        # self.targets.setdefault(sub_target, {})
        ekelund_range = []
        for index, points in enumerate(
                zip(self.tracks.values(), sub_target.tracks.values())):
            sub_a, sub_b = Submarine(*points[0], self.heading,
                                     self.speed), Submarine(
                                         *points[1], sub_target.heading,
                                         sub_target.speed)
            if not index:
                init_target_bearing = sub_a.get_target_bearing(sub_b)
                ekelund_range.append((0, 0, 0))
                continue
            current_target_bearing = sub_a.get_target_bearing(sub_b)
            bearing_rate = (current_target_bearing -
                            init_target_bearing) / self.interval
            cross_speed = sub_a.get_total_los_cross_speed(sub_b)
            calculate_range = abs(cross_speed / bearing_rate)
            ekelund_range.append(
                (round(bearing_rate, 2), round(cross_speed,
                                               1), round(calculate_range, 1)))
            init_target_bearing = current_target_bearing

            # print(f"{index}, observer {self.name},target_bearing: {sub_a.get_target_bearing(sub_b)}. target_range: true: {round(sub_a.get_target_range(sub_b), 2)}, calculate: {round(calculate_range, 2)}")
        self.targets[sub_target]["ekelund_range"] = ekelund_range


def run_scenario(submarines: list,
                 duration: int = 50,
                 interval: int = 3) -> None:
    for submarine in submarines:
        submarine.interval = interval
        assert submarine.leg_num == 0
        submarine._observe_target()

    index = 1
    while interval * index <= duration:
        for submarine in submarines:
            submarine._advance_one_leg()

        for submarine in submarines:
            submarine._observe_target()

        index += 1


def plot_tracks(sub_a: Submarine, sub_b: Submarine) -> None:
    sub01_tracks = list(sub_a.tracks.values())
    sub02_tracks = list(sub_b.tracks.values())
    assert len(sub01_tracks) == len(sub02_tracks)

    legend = [(round(a, 1), round(b, 1))
              for a, b in list(sub_a.targets[sub_b].values())]
    legend.append(sub_a.name)
    legend.append(sub_b.name)
    # legend.append((sub_a.__repr__(), sub_b.__repr__()))

    x1 = [i[0] for i in sub01_tracks]
    y1 = [i[1] for i in sub01_tracks]

    x2 = [i[0] for i in sub02_tracks]
    y2 = [i[1] for i in sub02_tracks]

    fig, ax = plt.subplots()

    # ax.plot(x1, y1,color='blue', label='A')
    # ax.plot(x2, y2,color='black', label='B')

    for i, j in zip(sub01_tracks, sub02_tracks):
        x = [i[0], j[0]]
        y = [i[1], j[1]]
        # ax.plot(x,y, 'g')
        ax.plot(x, y)

    ax.quiver(*sub01_tracks[-1],
              sub01_tracks[-1][0] - sub01_tracks[0][0],
              sub01_tracks[-1][1] - sub01_tracks[0][1],
              color="black",
              width=0.005)
    ax.quiver(*sub02_tracks[-1],
              sub02_tracks[-1][0] - sub02_tracks[0][0],
              sub02_tracks[-1][1] - sub02_tracks[0][1],
              color="blue",
              width=0.005)

    # 为了正确显示legend，前面的ax.plot 和 ax.quiver 的顺序不能变。
    ax.legend(legend, loc="upper left")

    ax.scatter(x1, y1, color="black", label="a", marker=".")
    ax.scatter(x2, y2, color="blue", label="b", marker=".")
    # ax.quiver(*track_01[-2], track_01[-1][0]-track_01[-2][0], track_01[-1][1]-track_01[-2][1])
    # ax.quiver(*track_02[-2], track_02[-1][0]-track_02[-2][0], track_02[-1][1]-track_02[-2][1])

    # plt.xlim([min(x1 + x2 + y1 + y2)-1, max(x1 + x2 + y1 + y2)+1])
    # plt.ylim([min(x1 + x2 + y1+ y2)-1, max(x1 + x2 + y1+ y2)+1])

    annotate_data = [[x, y + 0.2] for x, y in zip(x1, y1)]
    for annotate_point in annotate_data:
        plt.annotate("xx", xy=annotate_point)
    plt.grid(True)
    plt.show()


def test_data_setup():
    subs_los_movement_test_data = [
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 25, 6), 0),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 45, 6), 2),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 65, 6), 2),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 135, 6), 2),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 205, 6), 2),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 225, 6), 2),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 315, 6), 0),
        (Submarine(10, 10, 105, 6), Submarine(100, 100, 335, 6), 0),
        #
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 25, 6), 0),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 45, 6), 2),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 65, 6), 2),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 135, 6), 2),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 205, 6), 2),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 225, 6), 2),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 315, 6), 0),
        (Submarine(10, 10, 135, 6), Submarine(100, 100, 335, 6), 0),
        #
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 25, 6), 0),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 45, 6), 2),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 65, 6), 2),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 135, 6), 2),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 205, 6), 2),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 225, 6), 2),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 315, 6), 0),
        (Submarine(10, 10, 165, 6), Submarine(100, 100, 335, 6), 0),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 25, 6), 2),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 45, 6), 2),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 65, 6), 0),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 135, 6), 0),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 205, 6), 0),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 225, 6), 2),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 315, 6), 2),
        (Submarine(10, 10, 265, 6), Submarine(100, 100, 335, 6), 2),
        #
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 25, 6), 2),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 45, 6), 2),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 65, 6), 0),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 135, 6), 0),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 205, 6), 0),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 225, 6), 2),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 315, 6), 2),
        (Submarine(10, 10, 355, 6), Submarine(100, 100, 335, 6), 2),
        #
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 25, 6), 2),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 45, 6), 2),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 65, 6), 2),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 205, 6), 0),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 225, 6), 0),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 285, 6), 0),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 335, 6), Submarine(20, 10, 335, 6), 2),
        #
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 25, 6), 2),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 45, 6), 2),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 65, 6), 2),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 205, 6), 0),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 225, 6), 0),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 285, 6), 0),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 5, 6), Submarine(20, 10, 335, 6), 2),
        #
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 25, 6), 2),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 45, 6), 2),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 65, 6), 2),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 205, 6), 0),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 225, 6), 0),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 285, 6), 0),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 45, 6), Submarine(20, 10, 335, 6), 2),
        #
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 25, 6), 2),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 45, 6), 2),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 65, 6), 2),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 205, 6), 0),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 225, 6), 0),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 285, 6), 0),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 115, 6), Submarine(20, 10, 335, 6), 2),
        #
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 25, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 45, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 65, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 205, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 225, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 285, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 135, 6), Submarine(20, 10, 335, 6), 2),
        #
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 25, 6), 0),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 45, 6), 0),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 65, 6), 0),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 205, 6), 2),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 225, 6), 2),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 285, 6), 2),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 185, 6), Submarine(20, 10, 335, 6), 0),
        #
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 25, 6), 0),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 45, 6), 0),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 65, 6), 0),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 135, 6), 2),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 205, 6), 2),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 225, 6), 2),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 285, 6), 2),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 315, 6), 2),
        (Submarine(10, 20, 285, 6), Submarine(20, 10, 335, 6), 0),
    ]

    subs_bearing_test_data = [
        (Submarine(10, 10, 105, 6), Submarine(10, 20, 25, 6), 0),
        (Submarine(10, 10, 105, 6), Submarine(20, 20, 25, 6), 45),
        (Submarine(10, 10, 105, 6), Submarine(20, 10, 25, 6), 90),
        (Submarine(10, 10, 105, 6), Submarine(20, 0, 25, 6), 135),
        (Submarine(10, 10, 105, 6), Submarine(10, 0, 25, 6), 180),
        (Submarine(10, 10, 105, 6), Submarine(0, 0, 25, 6), 225),
        (Submarine(10, 10, 105, 6), Submarine(0, 10, 25, 6), 270),
        (Submarine(10, 10, 105, 6), Submarine(0, 20, 25, 6), 315),
        #
    ]
    return subs_bearing_test_data, subs_los_movement_test_data


def test_bearing():
    subs_bearing_test, subs_los_movement_test = test_data_setup()
    for index, submarine in enumerate(subs_bearing_test):
        a, b, expecting = submarine
        if a.get_target_bearing(b) != expecting:
            print("-" * 111)
            print(a.get_target_bearing(b))
            print(subs_bearing_test[index])


def test_relative_movement():
    subs_bearing_test, subs_los_movement_test = test_data_setup()
    for index, submarine in enumerate(subs_los_movement_test):
        a, b, expecting = submarine
        if b.get_relative_movement_type(a) != expecting:
            print("-" * 111)
            print(subs_los_movement_test[index])
        if a.get_relative_movement_type(b) != expecting:
            print("-" * 111)
            print(subs_los_movement_test[index])


def test_cross_los_speed():
    subs_bearing_test, subs_los_movement_test = test_data_setup()
    for index, submarine in enumerate(subs_los_movement_test):
        a, b, expecting = submarine
        if expecting == 0:
            manual_cal_speed = round(
                a.get_los_cross_speed(b) + b.get_los_cross_speed(a), 2)
        else:
            manual_cal_speed = round(
                abs(a.get_los_cross_speed(b) - b.get_los_cross_speed(a)), 2)
        # print(manual_cal_speed)
        if manual_cal_speed != round(a.get_total_los_cross_speed(b), 2):
            print("-" * 111)
            print(subs_los_movement_test[index])


def test_range():
    subs_bearing_test, subs_los_movement_test = test_data_setup()
    for index, submarine in enumerate(subs_los_movement_test):
        a, b, expecting = submarine
        print("-" * 111)
        print(subs_los_movement_test[index])
        print(a.get_target_range(b))


def test01():
    sub_a, sub_b, _ = (Submarine(30, 20, 285, 6), Submarine(20, 10, 125, 6), 0)
    sub_a.add_target(sub_b)

    run_scenario([sub_a, sub_b], 80, 5)

    sub_a.calculate_ekelund_range(sub_b)

    # plot_tracks(sub_a, sub_b)

    t1 = [(round(i[0], 3), round(i[1], 3)) for i in sub_a.tracks.values()]
    t2 = [(round(i[0], 3), round(i[1], 3)) for i in sub_b.tracks.values()]
    # t1 = [(round(i[0], 1), round(i[1], 1)) for i in sub_a.tracks.values()]
    # t2 = [(round(i[0], 1), round(i[1], 1)) for i in sub_b.tracks.values()]
    # t1 = [(round(i[0]), round(i[1])) for i in sub_a.tracks.values()]
    # t2 = [(round(i[0]), round(i[1])) for i in sub_b.tracks.values()]

    data = []
    links = []
    for index, points in enumerate(zip(t1, t2)):
        item_a, item_b = points
        # print(item_a, item_b)
        name_a, name_b = f"a{index}", f"b{index}"
        # print(name_a, name_b)
        data.extend([
            {
                "name": name_a,
                "x": item_a[0],
                "y": item_a[1]
            },
            {
                "name": name_b,
                "x": item_b[0],
                "y": item_b[1]
            },
        ])
        links.extend([{"source": name_a, "target": name_b}])
    return (data, links)


def _generate_track_data(sub: Submarine):
    # res = []
    # for index, item in enumerate(sub.tracks.values()):
    #     new_item = [round(item[0], 2), round(item[1], 2)]
    #     if not index:
    #         prev = new_item
    #     else:
    #         res.append([prev, new_item])
    #         prev = new_item
    # return res
    track_data = list(sub.tracks.values())
    res = []
    return [[
        (round(track_data[0][0], 2), round(track_data[0][1], 2)),
        (round(track_data[-1][0], 2), round(track_data[-1][1], 2)),
    ]]


def cal_target_data(sub_a: Submarine = None,
                    sub_b: Submarine = None,
                    duration: int = 60,
                    interval: int = 3):
    if sub_a is None or sub_b is None:
        sub_a, sub_b, _ = (Submarine(50, 40, 325,
                                     6), Submarine(40, 30, 85, 10), 0)

    sub_a.add_target(sub_b)

    run_scenario([sub_a, sub_b], duration, interval)
    sub_a.calculate_ekelund_range(sub_b)
    # plot_tracks(sub_a, sub_b)

    t1 = [(round(i[0], 3), round(i[1], 3)) for i in sub_a.tracks.values()]
    t2 = [(round(i[0], 3), round(i[1], 3)) for i in sub_b.tracks.values()]
    datas = []
    max_x = 0
    min_x = 9999999
    max_y = 0
    min_y = 9999999

    for index, points in enumerate(zip(t1, t2)):
        item_a, item_b = points
        y_high = max(item_a[1], item_b[1])
        y_low = min(item_a[1], item_b[1])
        x_high = max(item_a[0], item_b[0])
        x_low = min(item_a[0], item_b[0])

        max_x = x_high if x_high > max_x else max_x
        max_y = y_high if y_high > max_y else max_y
        min_x = x_low if x_low < min_x else min_x
        min_y = y_low if y_low < min_y else min_y

        # print(item_a, item_b)
        # continue

        # name = f"T0{index}"  if index < 10 else f"T{index}"
        name = f"T{index}"
        datas.append({"name": name, "line": [item_a, item_b]})

    length_x = max_x - min_x
    length_y = max_y - min_y
    length_diff = length_x - length_y
    if length_diff > 0:
        max_y += length_diff / 2
        min_y -= length_diff / 2
    else:
        max_x += abs(length_diff / 2)
        min_x -= abs(length_diff / 2)

    target_true_data = [(round(v[0], 1), round(v[1], 1))
                        for k, v in sub_a.targets[sub_b].items()
                        if isinstance(k, int)]
    target_ekelund_data = sub_a.targets[sub_b]["ekelund_range"]
    own_tracks = _generate_track_data(sub_a)
    target_tracks = _generate_track_data(sub_b)
    # print("-" * 111)
    # print(own_tracks)
    # print(target_tracks)
    # print("-" * 111)
    # print(sub_a)
    # print(sub_b)
    return {
        "datas": datas,
        "target_true_data": target_true_data,
        "target_ekelund_data": target_ekelund_data,
        "own_tracks": own_tracks,
        "target_tracks": target_tracks,
        "max_x": round(max_x) + 1,
        "min_x": round(min_x) - 1,
        "max_y": round(max_y) + 1,
        "min_y": round(min_y) - 1,
    }

    # for point_a, point_b in zip(t1,t2):
    #     datas.append([point_a, point_b])
    # return datas

    # for index, points in enumerate(zip(t1, t2)):
    #     item_a, item_b = points

    # print(item_a, item_b)
    # name_a, name_b = f"a{index}", f"b{index}"
    # data.extend(
    #     [
    #         {"name": name_a, "x": item_a[0], "y": item_a[1]},
    #         {"name": name_b, "x": item_b[0], "y": item_b[1]},
    #     ]
    # )
    # links.extend([{"source": name_a, "target": name_b}])
    # return (data, links)


def test03():
    a, b, c = (Submarine(30, 20, 265, 6), Submarine(20, 10, 65, 6), 0)
    e, f, c = (Submarine(30, 20, 265, 6), Submarine(20, 10, 65, 6), 0)
    print(a.OFFSPRINGS)


def generate_submarines(own_sub_data, target_sub_data, target_range,
                        target_bearing):
    # x,y = own_s
    own_x = 1000
    own_y = 1000
    target_x = own_x + target_range * math.sin(math.radians(target_bearing))
    target_y = own_y + target_range * math.cos(math.radians(target_bearing))
    return Submarine(own_x, own_y,
                     *own_sub_data), Submarine(target_x, target_y,
                                               *target_sub_data)


# print(generate_submarines((280, 10), (110, 8), 15, 200))


def main():
    # run_scenario(50)
    print(
        cal_target_data(*(generate_submarines((280, 10), (110, 8), 15, 200))))
    # print(generate_submarines((280, 10), (110, 8), 15, 200))


if __name__ == "__main__":
    main()
